#include "test_frame.h"
#include <stdio.h>
#include <iostream>
#include "writer.h"
#include "stringbuffer.h"
#include "wb_platform.h"
#include "WebSocketManager.h"

using namespace rapidjson;
#include<iostream>

using namespace std;

void TestEvent::on_connect_notify(uint32_t result){
	cout << "app on connect notify result:" << result << endl;
    // tcp连接成功后发送登录连接
    uint8_t buf[1024] = { 0 };
    uint32_t len = 0;
    pack_login_req(UID, buf, len); // 获取返回的buf和len
    reliable_send_message(MSGID_Login_Req, buf, len);
}

void TestEvent::on_disconnect_notify(){
	cout << "app on dis connect notify" << endl;
    // 其他地方登陆了 强制退出
    [WebSocketManager.sharedInstance testForceLogout_Noti];
}

void TestEvent::on_reconnect_notify(uint32_t notify_code){
	cout << "app on re connect notify code:"<<notify_code << endl;
}

void TestEvent::on_error(uint32_t code){
	cout << "app on error code:" << code << endl;
}

void TestEvent::on_message(uint16_t msgid, const uint8_t* buf, uint16_t buf_len){
	char tmp_buf[10 * 1024] = { 0 };
	memcpy(tmp_buf, buf, buf_len);
	cout << "app  on recvd msgid:" << msgid << " msgname:"<<get_msg_name(msgid)<< " , datalen:" << buf_len <<" data:"<< (char*)tmp_buf<< endl;
	if (msgid == MSGID_Login_Resp){
		//decode body
		parse_login_resp(tmp_buf, buf_len);
	} else if (msgid == WS_MsgID_AddCourse_Noti || msgid == WS_MsgID_UpdateCourse_Noti || msgid == WS_MsgID_DeleteCourse_Noti || msgid == WS_MsgID_CourseAlmostStart_Noti || msgid == WS_MsgID_CourseAlreadyStart_Noti) {
        // 课程相关
        [WebSocketManager.sharedInstance testEventOnMessage];
    } else if (msgid == WS_MsgID_ForceLogout_Noti) {
        // 其他地方登陆了 强制退出
        [WebSocketManager.sharedInstance testForceLogout_Noti];
    }
}
void TestEvent::parse_login_resp(const char* buf, uint16_t buf_len){
	rapidjson::Document doc;
	if (!doc.Parse(buf).HasParseError()){
		if (doc.HasMember("start_seq") && doc["start_seq"].IsInt()){
			int start_seq = doc["start_seq"].GetInt();
			cout << "app  login response with uid:" << uid_ << ", start_seq:" << start_seq << endl;
			//frame_->set_uid(uid_, start_seq);
		}
	}
}

void TestEvent::get_heartbeat_status(const uint8_t* buf, uint16_t max_len, uint16_t &len)
{
    snprintf((char*)buf, max_len, "{\"user_status\":%d}", 2);
    len = strlen((const char*)buf);
}


const char* get_msg_name(uint16_t msgid){
	switch (msgid){
	case MSGID_Login_Req:
		return "MSGID_Login_Req";
	case MSGID_Login_Resp:
		return "MSGID_Login_Resp";
	case MSGID_HeartBeat:
		return "MSGID_HeartBeat";
	case MSGID_Logout_Req:
		return "MSGID_Logout_Req";
	case MSGID_Logout_Resp:
		return "MSGID_Logout_Resp";
	case WS_MsgID_Broadcast_Noti:
		return "WS_MsgID_Broadcast_Noti";
	case WS_MsgID_AddCourse_Noti:
		return "WS_MsgID_AddCourse_Noti";
	case WS_MsgID_UpdateCourse_Noti:
		return "WS_MsgID_UpdateCourse_Noti";
	case WS_MsgID_DeleteCourse_Noti:
		return "WS_MsgID_DeleteCourse_Noti";
	case WS_MsgID_CourseAlmostStart_Noti:
		return "WS_MsgID_CourseAlmostStart_Noti";
	case WS_MsgID_CourseAlreadyStart_Noti:
		return "WS_MsgID_CourseAlreadyStart_Noti";
	case WS_MsgID_CourseOver_Noti:
		return "WS_MsgID_CourseOver_Noti";
	case WS_MsgID_ForceLogout_Noti:
		return "WS_MsgID_ForceLogout_Noti";
	default:
		return "unknow msgid";
	}
	return "unkonwn msgid";
}



void sdk_log_cb(int level, const char* msg){
    cout << "sdk log level:" << level << ", msg:" << msg << endl;
}


void pack_login_req(uint32_t uid, const uint8_t* buf, uint32_t& out_len){
    Document document;
    document.SetObject();
    Value value;
    value.SetInt(uid);
    
    Document::AllocatorType& allocator = document.GetAllocator();
    
    document.AddMember("uid", value, allocator);
    
    value.SetInt(10);
    document.AddMember("client_type", value, allocator);
    
    value.SetInt(1); //network reconnect
    //value.SetInt(2); //user real login
    document.AddMember("reconnect", value, allocator);
    
    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);
    document.Accept(writer);
    std::string out = buffer.GetString();
    cout << "output json:" << out << endl;
    out_len = out.size();
    memcpy((void*)buf, out.c_str(), out_len);
}

void pack_heartbeat_req(uint32_t uid, const uint8_t* buf, uint32_t& out_len){
    Document document;
    document.SetObject();
    Value value;
    value.SetInt(uid);
    Document::AllocatorType& allocator = document.GetAllocator();
    
    document.AddMember("token", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJiaXoiOiJjbGFzc2luIiwiZXhwaXJlIjoiMTU1OTc5ODcyMyIsInVpZCI6IjU3MDQzNzY2NSJ9.uagfBp6uiOXxOeEEKI6c7VZRF2IGWNQZRlEZSuERfb8", allocator);
    
    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);
    document.Accept(writer);
    std::string out = buffer.GetString();
    out_len = out.size();
    memcpy((void*)buf, out.c_str(), out_len);
}

// 设置sdk的token 以及心跳包
void set_token_heartbeat_req(uint32_t len, const char* token, uint32_t uid,const uint8_t* buf) {
    int counter = 0;
    while (true){
        su_sleep(1,0);
        counter++;
        reliable_set_token((const uint8_t*)token, strlen(token));
        if ((counter % 20) == 0){
            len = 0;
            pack_heartbeat_req(uid, buf, len);
        }
    }
}


